package message

import (
	"errors"
//		"log"
	"msgsign"
	"net"
	"strconv"
	"strings"
)

type Head struct {
	Key   string
	Value string
}

type Message struct {
	Heads []*Head
	Body  []byte
}

func (h *Message) GetHeadValue(key string) string {

	for _, value := range h.Heads {
		if value.Key == key {

			return (value.Value)
		}
	}
	return ""
}

func SendMessageByConn(conn net.Conn, msg []byte) error {
	if conn == nil {
		return errors.New(msgsign.NO_USER)

	}
	_, err := conn.Write(msg)
	if err != nil {
		return errors.New(msgsign.SEND_FAIL)
	}
	return nil
}

func MessageToByte(m *Message) []byte {
	data := make([]byte, 0)
	for _, value := range m.Heads {
		buf := []byte(value.Key + ":" + value.Value + "\r\n")
		data = append(data, buf...)

	}
	leng := strconv.Itoa(len(m.Body))
	headlength := []byte(msgsign.LENGTH + ":" + leng + "\r\n")
	data = append(data, headlength...)
	buf := []byte("\r\n")
	data = append(data, buf...)
	if len(m.Body) > 0 {
		data = append(data, m.Body...)
	}
	end := []byte("-\r\n-")
	data = append(data, end...)
	Network_flow = Network_flow + (int64)(len(data))
	return data
}

var Network_flow int64 = 0

func BytesToMessage(buf []byte) []*Message {

	Network_flow = Network_flow + (int64)(len(buf))
	data := make([]*Message, 0)
	start := 0
	var read bool = false
//		if !read{
//			
//			log.Println(string(buf))
//			
//			}
	for i := 0; i < len(buf); i++ {
		
		
		if read || len(buf) > i+8 {
			if buf[i] == '-' && buf[i+1] == '\r' && buf[i+2] == '\n' && buf[i+3] == '-' {
				i = i + 4
				start = i
			}
			if !read && (buf[i] == 'T' && buf[i+1] == 'y' && buf[i+2] == 'p' && buf[i+3] == 'e') {
				read = true
			}
			if (start == i) && (len(buf) > start+4) && (!(buf[start] == 'T' && buf[start+1] == 'y' && buf[start+2] == 'p' && buf[start+3] == 'e')) {
				break
			}
			if buf[i] == '\r' && buf[i+1] == '\n' && buf[i+2] == '\r' && buf[i+3] == '\n' {
				var bodylength int = 0
				var msg Message
				hb := make([]byte, 0)
				hb = append(hb, buf[start:i]...)

				hbstr := string(hb)
				hbarray := strings.Split(hbstr, "\r\n")
				hbs := make([]*Head, 0)
				for _, value := range hbarray {
					if len(value) == 0 {
						continue
					} else {
						var hd Head
						headers := strings.Split(value, ":")
						hd.Key = headers[0]
						hd.Value = headers[1]
						if hd.Key == msgsign.LENGTH {
							bodylength, _ = strconv.Atoi(hd.Value)
						} else {
							hbs = append(hbs, &hd)
						}

					}

				}
				if bodylength > 0 {
					body := make([]byte, 0)
					body = append(body, buf[i+4:i+4+bodylength]...)
					msg.Body = body
				}
				msg.Heads = hbs
				data = append(data, &msg)
				i = i + 3 + bodylength
				read = false
			}

		} else {
			break
		}
	}
	return data
}

//func StartLogin() []byte {
//	var msg Message
//	msg.Heads = []*Head{&Head{msgsign.TYPR, msgsign.LOGIN}, &Head{msgsign.RESULT, msgsign.START}}
//	return MessageToByte(&msg)
//}

func Logout() []byte {
	var msg Message
	msg.Heads = []*Head{&Head{msgsign.TYPR, msgsign.LOGIN}, &Head{msgsign.STATUS, msgsign.LOGOUT}}
	return MessageToByte(&msg)
}
